#pragma once

#include "fxcc/core/graph/opengl3/pch.h"
#include "fxcc/core/graph/opengl3/ShaderFile.h"
#include "fxcc/core/graph/opengl3/Program.h"

namespace fxcc
{
    namespace graph
    {
        namespace opengl3
        {

            struct FXCC_API ShaderDesc
            {
                std::string m_VertCode;
                std::string m_FragCode;
                std::string m_GeometryCode;
                std::string m_TessellationControlCode;
                std::string m_TessellationEvalutionCode;
                std::string m_ComputeCode;

                void OutDirDebug(const std::string& dir)
                {
                    if (!fs::exists(dir))
                    {
                        fs::create_directories(dir);
                    }
                    OutText((fs::path(dir) / "vert.glsl").string(), m_VertCode);
                    OutText((fs::path(dir) / "frag.glsl").string(), m_FragCode);
                    OutText((fs::path(dir) / "geo.glsl").string(), m_GeometryCode);
                    OutText((fs::path(dir) / "tcs.glsl").string(), m_TessellationControlCode);
                    OutText((fs::path(dir) / "tes.glsl").string(), m_TessellationEvalutionCode);
                    OutText((fs::path(dir) / "compute.glsl").string(), m_ComputeCode);
                }
                void OutText(const std::string& p, const std::string v)
                {
                    std::ofstream ofs(p);
                    ofs << v;
                    ofs.flush();
                    ofs.close();
                }
            };

            struct FXCC_API Shader : public fxcc::graph::opengl3::Program
            {
                ShaderDesc m_Desc;

                Shader(const ShaderDesc& desc);
                
                Shader(const std::string& vCode, const std::string& fCode);
                
                bool Init();

                bool Init1();

                bool AttachCode(const std::string& code, int shaderType);

                static void DispatchCompute(int x, int y, int z);

            public:
                void UseMaterial(const fxcc::graph::common::MaterialView& material);

                void UseMaterialParam(const fxcc::graph::common::Params& params);

                void UseTextureIndex(const fxcc::graph::common::TextureMaps& textureMaps);

                void UseTextureMaps(const fxcc::graph::common::TextureMaps& textureMaps);
            };


        };
    }
};